<!DOCTYPE html>



  


<html class="theme-next muse use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta name="baidu-site-verification" content="UqlC4pwKIm">
  <meta name="baidu-site-verification" content="d3U0dGeqGw">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">



  
  
    
    
  <script src="/lib/pace/pace.min.js?v=1.0.2"></script>
  <link href="/lib/pace/pace-theme-minimal.min.css?v=1.0.2" rel="stylesheet">







<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">



  <meta name="google-site-verification" content="9Ho8iwjF7bDNkvQpVQHlhFPHnsfuMWlsOvTTgEPIuy4">














  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">




  
  
  
  

  
    
    
  

  

  
    
      
    

    
  

  
    
      
    

    
  

  
    
      
    

    
  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Roboto Slab:300,300italic,400,400italic,700,700italic|Roboto Slab:300,300italic,400,400italic,700,700italic|Lobster Two:300,300italic,400,400italic,700,700italic|PT Mono:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  







<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.3" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="https://cdn.jsdelivr.net/gh/lopyfrontend/common@0.0.1/icon/favicon-180x180.png?v=5.1.3">


  <link rel="icon" type="image/png" sizes="32x32" href="https://cdn.jsdelivr.net/gh/lopyfrontend/common@0.0.1/icon/favicon-32x32.png?v=5.1.3">


  <link rel="icon" type="image/png" sizes="16x16" href="https://cdn.jsdelivr.net/gh/lopyfrontend/common@0.0.1/icon/favicon-16x16.png?v=5.1.3">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.3" color="#222">





  <meta name="keywords" content="docker,develop,swarm,learn,">





  <link rel="alternate" href="/atom.xml" title="码奴假娃" type="application/atom+xml">






<meta name="description" content="尝试一下docker-swarm之hello world">
<meta name="keywords" content="docker,develop,swarm,learn">
<meta property="og:type" content="article">
<meta property="og:title" content="开始尝试使用swarm之第三篇-多节点操作">
<meta property="og:url" content="https://blog.lopygo.com/2021/2021-11-13-try-using-docker-swarm-node2/index.html">
<meta property="og:site_name" content="码奴假娃">
<meta property="og:description" content="尝试一下docker-swarm之hello world">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2025-09-16T17:33:20.685Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="开始尝试使用swarm之第三篇-多节点操作">
<meta name="twitter:description" content="尝试一下docker-swarm之hello world">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Muse',
    version: '5.1.3',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":true,"onmobile":true},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: 'undefined',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://blog.lopygo.com/2021/2021-11-13-try-using-docker-swarm-node2/">





  <title>开始尝试使用swarm之第三篇-多节点操作 | 码奴假娃</title>
  




<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
            (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
  ga('create', 'UA-136884610-2', 'auto');
  ga('send', 'pageview');
</script>


  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?52567a573db99b54cccb66af4c41822b";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">码奴假娃</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <h1 class="site-subtitle" itemprop="description">裸皮狗</h1>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br>
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-commonweal">
          <a href="/404.html" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-heartbeat"></i> <br>
            
            公益404
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br>
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://blog.lopygo.com/2021/2021-11-13-try-using-docker-swarm-node2/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Tony Java Z">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="码奴假娃">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">开始尝试使用swarm之第三篇-多节点操作</h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2021-11-13T05:37:52+00:00">
                2021-11-13
              </time>
            

            
              <span class="post-meta-divider">|</span>
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-check-o"></i>
              </span>
              
                <span class="post-meta-item-text">更新于&#58;</span>
              
              <time title="更新于" itemprop="dateModified" datetime="2025-09-16T17:33:20+00:00">
                2025-09-17
              </time>
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/develop/" itemprop="url" rel="index">
                    <span itemprop="name">develop</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          
             <span id="/2021/2021-11-13-try-using-docker-swarm-node2/" class="leancloud_visitors" data-flag-title="开始尝试使用swarm之第三篇-多节点操作">
               <span class="post-meta-divider">|</span>
               <span class="post-meta-item-icon">
                 <i class="fa fa-eye"></i>
               </span>
               
                 <span class="post-meta-item-text">阅读次数&#58;</span>
               
                 <span class="leancloud-visitors-count"></span>
             </span>
          

          
            <span class="post-meta-divider">|</span>
            <span class="page-pv"><i class="fa fa-file-o"></i>
            <span class="busuanzi-value" id="busuanzi_value_page_pv"></span>
            </span>
          

          
            <div class="post-wordcount">
              
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">字数统计&#58;</span>
                
                <span title="字数统计">
                  2,064
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                
                <span title="阅读时长">
                  10
                </span>
              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <script src="/assets/js/APlayer.min.js"> </script><p>尝试一下docker-swarm之hello world<br><a id="more"></a>  </p>
<h1 id="前文回顾"><a href="#前文回顾" class="headerlink" title="前文回顾"></a>前文回顾</h1><p>接上文，本文一共在虚拟机上运行了三个节点。它们都是管理节点。然后对service做了一些简单的增删查操作</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">docker node  ls</span><br><span class="line"><span class="comment"># ID                            HOSTNAME       STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION</span></span><br><span class="line"><span class="comment">#xgjnkzvysal5fv7ugm1t5d7zr *   swarmmanger    Ready     Active         Leader           20.10.21</span></span><br><span class="line"><span class="comment">#e3ye8fep0dr3xkxrzdxz8wzjw     swarmworker1   Ready     Active         Reachable        20.10.21</span></span><br><span class="line"><span class="comment">#i5vz5saiixnx82j9hpy4d5wmc     swarmworker2   Ready     Active         Reachable        20.10.21</span></span><br></pre></td></tr></table></figure>
<p>在这3个节点上，本文就要开始做多节点方面的操作</p>
<h1 id="Task"><a href="#Task" class="headerlink" title="Task"></a>Task</h1><p>什么是task</p>
<p>大意就是服务的执行者，一个服务通过多个task来执行服务</p>
<p>swarm的task之于service相当于：</p>
<p>面向对像的object之于class；</p>
<p>docker的container之于images；</p>
<p>一个服务可有多个task，并且通过内部算法，部署在一个或多个node上</p>
<p>处理各类任务的，也是这些task</p>
<p>设置task个数的参数为<code>replicas</code>，即复制品或副本…</p>
<p>那么我们来试一下</p>
<h1 id="创建多task的service并指定node"><a href="#创建多task的service并指定node" class="headerlink" title="创建多task的service并指定node"></a>创建多task的service并指定node</h1><p>现在，我们一共3个节点，创建服务时将<code>replicas</code>设为2</p>
<p>分别按以下条件指定<code>--constraint</code> 参数</p>
<p>由于遇到一些问题，此时再次查看一下node数量 </p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">docker node ls</span><br><span class="line"><span class="comment"># ID                            HOSTNAME       STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION</span></span><br><span class="line"><span class="comment"># xgjnkzvysal5fv7ugm1t5d7zr *   swarmmanger    Ready     Active         Leader           20.10.21</span></span><br><span class="line"><span class="comment"># e3ye8fep0dr3xkxrzdxz8wzjw     swarmworker1   Ready     Active         Reachable        20.10.21</span></span><br><span class="line"><span class="comment"># 61yvp61wb1ojwytecc7d8vtcf     swarmworker2   Down      Active                          20.10.21</span></span><br><span class="line"><span class="comment"># hmekztyy9ux1soi3mg7xde7f5     swarmworker2   Ready     Active                          20.10.21</span></span><br><span class="line"><span class="comment"># i5vz5saiixnx82j9hpy4d5wmc     swarmworker2   Down      Active                          20.10.21</span></span><br></pre></td></tr></table></figure>
<p>swarmworker2因为遇到了问题，前后执行了两次leave，导致id发生了变化。从<code>status</code>看，只有3个是<code>ready</code>的</p>
<h2 id="不指定条件"><a href="#不指定条件" class="headerlink" title="不指定条件"></a>不指定条件</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">service create --replicas 2 --name hello_without_constraint  alpine ping docker.com</span><br><span class="line"><span class="comment"># rbzl783j0ngiu5apkc3ivuz8m</span></span><br><span class="line"><span class="comment"># overall progress: 2 out of 2 tasks</span></span><br><span class="line"><span class="comment"># 1/2: running   [==================================================&gt;]</span></span><br><span class="line"><span class="comment"># 2/2: running   [==================================================&gt;]</span></span><br><span class="line"><span class="comment"># verify: Service converged</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">docker service ps  hello_without_constraint</span><br><span class="line"><span class="comment"># ID             NAME                         IMAGE           NODE           DESIRED STATE   CURRENT STATE            ERROR     PORTS</span></span><br><span class="line"><span class="comment"># 9abhtllls5yu   hello_without_constraint.1   alpine:latest   swarmworker2   Running         Running 23 seconds ago</span></span><br><span class="line"><span class="comment"># ts72jny9a066   hello_without_constraint.2   alpine:latest   swarmworker1   Running         Running 25 seconds ago</span></span><br></pre></td></tr></table></figure>
<p>经多次设置，task应该是通过某种算法均匀分布在所有node上的。表现为尽可能给所有节点平滩。据经验，分配方式肯定可以配置的，比如设权重之类的</p>
<h2 id="指定hostname"><a href="#指定hostname" class="headerlink" title="指定hostname"></a>指定hostname</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">docker service create --replicas 2 --constraint node.hostname==swarmworker1 --name hello alpine ping docker.com</span><br><span class="line"><span class="comment">#0fz44crhpw73te5t6hva5gsaq</span></span><br><span class="line"><span class="comment">#overall progress: 2 out of 2 tasks</span></span><br><span class="line"><span class="comment">#1/2: running   [==================================================&gt;]</span></span><br><span class="line"><span class="comment">#2/2: running   [==================================================&gt;]</span></span><br><span class="line"><span class="comment">#verify: Service converged</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 在两台机器上运行以下命令，结果一致</span></span><br><span class="line">docker service ls</span><br><span class="line"><span class="comment">#ID             NAME      MODE         REPLICAS   IMAGE           PORTS</span></span><br><span class="line"><span class="comment">#0fz44crhpw73   hello     replicated   2/2        alpine:latest</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 在两台机器上运行以下命令，结果一致。可以看到，两个task运行在两个不同的节点上</span></span><br><span class="line">docker service ps hello</span><br><span class="line"><span class="comment">#ID             NAME          IMAGE           NODE           DESIRED STATE   CURRENT STATE                ERROR                              PORTS</span></span><br><span class="line"><span class="comment">#kh1um6dqg31d   hello.1       alpine:latest   swarmworker1   Running         Running about a minute ago</span></span><br><span class="line"><span class="comment">#5jttfmry1nm9   hello.2       alpine:latest   swarmworker1   Running         Running about a minute ago</span></span><br></pre></td></tr></table></figure>
<p>可见，分配到指定hostname的节点上了</p>
<p>多个节点的hostname理论上是可以重复的，这个有空再说吧</p>
<h2 id="指定节点类型"><a href="#指定节点类型" class="headerlink" title="指定节点类型"></a>指定节点类型</h2><p>节点类型就两种，worker和manager</p>
<p>那么本次我们先将worker2降级成worker类型，那么，有两个管理节点和一个工作节点</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">docker node demote swarmworker2</span><br><span class="line"><span class="comment">#Manager swarmworker2 demoted in the swarm.</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">docker node  ls</span><br><span class="line"><span class="comment">#ID                            HOSTNAME       STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION</span></span><br><span class="line"><span class="comment">#xgjnkzvysal5fv7ugm1t5d7zr *   swarmmanger    Ready     Active         Leader           20.10.21</span></span><br><span class="line"><span class="comment">#e3ye8fep0dr3xkxrzdxz8wzjw     swarmworker1   Ready     Active         Reachable        20.10.21</span></span><br><span class="line"><span class="comment">#i5vz5saiixnx82j9hpy4d5wmc     swarmworker2   Ready     Active                          20.10.21</span></span><br></pre></td></tr></table></figure>
<p>键入以下命令将服务的task分布在管理节点</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">docker service create --replicas 4 --constraint node.role==manager --name hello_by_role alpine ping docker.com</span><br><span class="line"><span class="comment">#af7xj2jrqgfjsy35klqrajltv</span></span><br><span class="line"><span class="comment">#overall progress: 4 out of 4 tasks</span></span><br><span class="line"><span class="comment">#1/4: running   [==================================================&gt;]</span></span><br><span class="line"><span class="comment">#2/4: running   [==================================================&gt;]</span></span><br><span class="line"><span class="comment">#3/4: running   [==================================================&gt;]</span></span><br><span class="line"><span class="comment">#4/4: running   [==================================================&gt;]</span></span><br><span class="line"><span class="comment">#verify: Service converged</span></span><br><span class="line"></span><br><span class="line">docker service ps hello_by_role</span><br><span class="line"><span class="comment"># ID             NAME              IMAGE           NODE           DESIRED STATE   CURRENT STATE            ERROR     PORTS</span></span><br><span class="line"><span class="comment"># py8yy13tqcvg   hello_by_role.1   alpine:latest   swarmmanger    Running         Running 49 seconds ago</span></span><br><span class="line"><span class="comment"># 4xfukh7i7tue   hello_by_role.2   alpine:latest   swarmworker1   Running         Running 50 seconds ago</span></span><br><span class="line"><span class="comment"># fmd8xxkexrxl   hello_by_role.3   alpine:latest   swarmmanger    Running         Running 49 seconds ago</span></span><br><span class="line"><span class="comment"># wqlnuvy34a7j   hello_by_role.4   alpine:latest   swarmworker1   Running         Running 50 seconds ago</span></span><br></pre></td></tr></table></figure>
<h2 id="指定label"><a href="#指定label" class="headerlink" title="指定label"></a>指定label</h2><p>就不多做了，内容都差不多。。官网看吧</p>
<blockquote>
<p><a href="https://docs.docker.com/engine/swarm/services/#placement-constraints" target="_blank" rel="noopener">https://docs.docker.com/engine/swarm/services/#placement-constraints</a></p>
</blockquote>
<h1 id="关于端口"><a href="#关于端口" class="headerlink" title="关于端口"></a>关于端口</h1><p>一般情况，我们用http来提供无状态的服务，就会涉及到端口的暴露和分布的问题</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 目前有两个节点，下面我们建一个replicas=1的nginx服务，暴露端口为8080，容器内部端口为80，即8080转发到80</span></span><br><span class="line">docker service create --name my_web --replicas 1 --publish published=8080,target=80 nginx</span><br><span class="line"><span class="comment">#k7w0xq3n9in3ttdfggg6q0wc5</span></span><br><span class="line"><span class="comment">#overall progress: 1 out of 1 tasks</span></span><br><span class="line"><span class="comment">#1/1: running   [==================================================&gt;]</span></span><br><span class="line"><span class="comment">#verify: Service converged</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 查看nginx运行情况，发现运行在manager上</span></span><br><span class="line">docker service  ps my_web</span><br><span class="line"><span class="comment">#ID             NAME       IMAGE          NODE          DESIRED STATE   CURRENT STATE           ERROR     PORTS</span></span><br><span class="line"><span class="comment">#35pb8xxumb8p   my_web.1   nginx:latest   swarmmanger   Running         Running 5 minutes ago</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 此时，我们分别curl 两个节点的ip:端口</span></span><br><span class="line">curl http://192.0.0.30:8080/</span><br><span class="line"><span class="comment">#&lt;!DOCTYPE html&gt;</span></span><br><span class="line"><span class="comment">#&lt;html&gt;</span></span><br><span class="line"><span class="comment">#&lt;head&gt;</span></span><br><span class="line"><span class="comment">#&lt;title&gt;Welcome to nginx!&lt;/title&gt;</span></span><br><span class="line"><span class="comment"># ...</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 然后curl 另一个，发现结果是一样的</span></span><br><span class="line">curl http://192.0.0.31:8080/</span><br></pre></td></tr></table></figure>
<p>即内部有一套流量转发机制</p>
<p>引用官方</p>
<blockquote>
<p><a href="https://docs.docker.com/engine/swarm/services/#publish-ports" target="_blank" rel="noopener">https://docs.docker.com/engine/swarm/services/#publish-ports</a></p>
</blockquote>
<blockquote>
<p>You don’t need to know which nodes are running the tasks; connecting to port 8080 on any of the 10 nodes connects you to one of the three nginx tasks. You can test this using curl. The following example assumes that localhost is one of the swarm nodes. If this is not the case, or localhost does not resolve to an IP address on your host, substitute the host’s IP address or resolvable host name.</p>
</blockquote>
<p>大意是访问任何节点的该端口都会转发运行该服务的task的节点上（官方是10个节点，在3个节点上运行nginx，即–replicas 3）。</p>
<h1 id="机缘巧合发现个问题"><a href="#机缘巧合发现个问题" class="headerlink" title="机缘巧合发现个问题"></a>机缘巧合发现个问题</h1><p>另外，我发现个问题</p>
<p>由于第3个节点swarmworker2的没有配置代理，也没有提前去pull image</p>
<p>当我在执行 <code>docker service create ..... --replicas=2 ......</code> 的时候，恰好给swarmworker2分配了一个task</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">docker service create --replicas 2 --name hello_without_constraint  alpine ping docker.com</span><br><span class="line"><span class="comment"># b32kykwlr8gcpinfmpfugzkpy</span></span><br><span class="line"><span class="comment"># overall progress: 1 out of 2 tasks</span></span><br><span class="line"><span class="comment"># 1/2: preparing [=================================&gt;                 ]</span></span><br><span class="line"><span class="comment"># 2/2: running   [==================================================&gt;]</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 到这里就卡住了很久，开始我还以为是虚拟机卡了（毕竟电脑内存不大），一直找不到原因，没反应过来。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 然后我就ctrl+c 退出了，显示出以下信息（注意第一行的^C，是ctrl+c，也给打印出来了）</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ^COperation continuing in background.</span></span><br><span class="line"><span class="comment"># Use `docker service ps b32kykwlr8gcpinfmpfugzkpy` to check progress.</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 按提示，我执行了命令</span></span><br><span class="line">docker service ps b32kykwlr8gcpinfmpfugzkpy</span><br><span class="line"><span class="comment"># ID             NAME                         IMAGE           NODE           DESIRED STATE   CURRENT STATE                  ERROR     PORTS</span></span><br><span class="line"><span class="comment"># xnuy658s5b7u   hello_without_constraint.1   alpine:latest   swarmworker1   Running         Running about a minute ago</span></span><br><span class="line"><span class="comment"># cqft2hmpdbdu   hello_without_constraint.2   alpine:latest   swarmworker2   Running         Preparing about a minute ago</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 然后又多试了几次，发现，只要是在swarmworker2节点上，就启动不了</span></span><br><span class="line"><span class="comment"># 通过检查排除，发现是没有image。后台还在pull吧，这该死的网络，该死的gfw。</span></span><br></pre></td></tr></table></figure>
<p>这个问题我我也去了解了一下，就是节点只会用自己本地的image，不会用其它节点的。为什么不设计成节点共享呢，哪怕给个命令手动互相copy也行啊。</p>
<p>尤其对一些用于本地测试的私有image而言来说，就必须把image publish到仓库才行</p>
<p>怎么解决呢，要么手动 export/import</p>
<p>要么就自己搭个中转仓库</p>
<p>具体的情况，再搜搜吧</p>
<p>既然已经出了这档问题，顺便测试一下，直接将该节点剔除，看是什么反应</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 剔除之前</span></span><br><span class="line">docker service ps hello_without_constraint</span><br><span class="line"><span class="comment"># ID             NAME                         IMAGE           NODE           DESIRED STATE   CURRENT STATE             ERROR     PORTS</span></span><br><span class="line"><span class="comment"># xnuy658s5b7u   hello_without_constraint.1   alpine:latest   swarmworker1   Running         Running 8 minutes ago</span></span><br><span class="line"><span class="comment"># cqft2hmpdbdu   hello_without_constraint.2   alpine:latest   swarmworker2   Running         Preparing 8 minutes ago</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 在 swarmworker2 上执行leave，注意，只有工作节点才能leave，管理节点的话，要先降级成工作节点</span></span><br><span class="line">docker swarm leave</span><br><span class="line">Node left the swarm.</span><br><span class="line"></span><br><span class="line"><span class="comment"># 再在管理节点上查看service</span></span><br><span class="line">docker service ps hello_without_constraint</span><br><span class="line"><span class="comment"># ID             NAME                             IMAGE           NODE           DESIRED STATE   CURRENT STATE            ERROR     PORTS</span></span><br><span class="line"><span class="comment"># xnuy658s5b7u   hello_without_constraint.1       alpine:latest   swarmworker1   Running         Running 3 hours ago</span></span><br><span class="line"><span class="comment"># exf4xl00dttl   hello_without_constraint.2       alpine:latest   swarmmanger    Running         Running 13 seconds ago</span></span><br><span class="line"><span class="comment"># cqft2hmpdbdu    \_ hello_without_constraint.2   alpine:latest   swarmworker2   Shutdown        Preparing 3 hours ago</span></span><br></pre></td></tr></table></figure>
<p>由此可见 swarmworker2 关闭了，又从swarmmanger 启动了一个task</p>
<h1 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h1><p>在多个节点中：</p>
<p>要运行指定个数的task变得简单</p>
<p>对于使用网络端口对外作为服务的task，不用考虑task具体运行在哪些节点上，每个节点都能访问到task</p>
<p>如果某些task因为某些原因挂掉了，系统会自动帮忙重新运行新的task，并且在此节点池内，总个数不会变化</p>
<p>考虑到特定情况，将指定task运行在符合条件的node上也很容易</p>

      
    </div>
    
    
    

    

    

    
      <div>
        <ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者：</strong>
    Tony Java Z
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://blog.lopygo.com/2021/2021-11-13-try-using-docker-swarm-node2/" title="开始尝试使用swarm之第三篇-多节点操作">https://blog.lopygo.com/2021/2021-11-13-try-using-docker-swarm-node2/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>
    本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/" rel="external nofollow" target="_blank">CC BY-NC-SA 3.0</a> 许可协议。转载请注明出处！
  </li>
</ul>

      </div>
    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/docker/" rel="tag"># docker</a>
          
            <a href="/tags/develop/" rel="tag"># develop</a>
          
            <a href="/tags/swarm/" rel="tag"># swarm</a>
          
            <a href="/tags/learn/" rel="tag"># learn</a>
          
        </div>
      

      
      
        <div class="post-widgets">
        

        

        
          
          <div id="needsharebutton-postbottom">
            <span class="btn">
              <i class="fa fa-share-alt" aria-hidden="true"></i>
            </span>
          </div>
        
        </div>
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2021/2021-11-13-try-using-docker-swarm-node/" rel="next" title="开始尝试使用swarm之第二篇-节点类型">
                <i class="fa fa-chevron-left"></i> 开始尝试使用swarm之第二篇-节点类型
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2021/2021-11-13-try-using-docker-swarm-secrets/" rel="prev" title="try-using-docker-swarm-secrets">
                try-using-docker-swarm-secrets <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
      <div id="sidebar-dimmer"></div>
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/images/avatar.jpg" alt="Tony Java Z">
            
              <p class="site-author-name" itemprop="name">Tony Java Z</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

			<!--my custom code begin-->
			<script src="https://cdn.jsdelivr.net/npm/jquery@3.1.0/dist/jquery.min.js"></script>
			<script src="https://cdn.jsdelivr.net/npm/velocity-animate@1.5.0/velocity.min.js"></script>
			<script type="text/javascript">
			  $("#sidebar").hover(function(){
				$("#mydivshow").velocity('stop').velocity({opacity: 1});
			  },function(){
				$("#mydivshow").velocity('stop').velocity({opacity: 0});
			  });
			</script>
			<div id="mydivshow" class="mydivshow">
			<!--my custom code end-->
			
          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives">
              
                  <span class="site-state-item-count">118</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">17</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">104</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          
            <div class="feed-link motion-element">
              <a href="/atom.xml" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
            </div>
          

          <div class="links-of-author motion-element">
            
              
                <span class="links-of-author-item">
                  <a href="https://github.com/uljjmhn520" target="_blank" title="GitHub">
                    
                      <i class="fa fa-fw fa-github"></i>GitHub</a>
                </span>
              
                <span class="links-of-author-item">
                  <a href="mailto:284141050 @qq.com" target="_blank" title="Mail">
                    
                      <i class="fa fa-fw fa-envelope"></i>Mail</a>
                </span>
              
                <span class="links-of-author-item">
                  <a href="http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=pZedkZSRlJWQleXU1IvGysg" target="_blank" title="QQ邮我">
                    
                      <i class="fa fa-fw fa-envelope"></i>QQ邮我</a>
                </span>
              
            
          </div>

          
          

          
          
            <div class="links-of-blogroll motion-element links-of-blogroll-inline">
              <div class="links-of-blogroll-title">
                <i class="fa  fa-fw fa-link"></i>
                友情链接
              </div>
              <ul class="links-of-blogroll-list">
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.lopygo.com" title="主站" target="_blank">主站</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://blog.csdn.net/u011475210" title="WordZzzCsdn" target="_blank">WordZzzCsdn</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://wordzzzz.github.io" title="WordZzzGitPage" target="_blank">WordZzzGitPage</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.choudalao.com" title="臭大佬" target="_blank">臭大佬</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://blog.wingflare.com" title="翼闪的奶嘴" target="_blank">翼闪的奶嘴</a>
                  </li>
                
              </ul>
            </div>
          

          
        </div>
		<!--my custom code begin-->
		</div>
		<!--my custom code end-->
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#前文回顾"><span class="nav-number">1.</span> <span class="nav-text">前文回顾</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Task"><span class="nav-number">2.</span> <span class="nav-text">Task</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#创建多task的service并指定node"><span class="nav-number">3.</span> <span class="nav-text">创建多task的service并指定node</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#不指定条件"><span class="nav-number">3.1.</span> <span class="nav-text">不指定条件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#指定hostname"><span class="nav-number">3.2.</span> <span class="nav-text">指定hostname</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#指定节点类型"><span class="nav-number">3.3.</span> <span class="nav-text">指定节点类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#指定label"><span class="nav-number">3.4.</span> <span class="nav-text">指定label</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#关于端口"><span class="nav-number">4.</span> <span class="nav-text">关于端口</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#机缘巧合发现个问题"><span class="nav-number">5.</span> <span class="nav-text">机缘巧合发现个问题</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#小结"><span class="nav-number">6.</span> <span class="nav-text">小结</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; 2017 &mdash; <span itemprop="copyrightYear">2025</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Tony Java Z</span>

  
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
    
      <span class="post-meta-item-text">Site words total count&#58;</span>
    
    <span title="Site words total count">72.9k</span>
  
</div>






  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Muse</a></div>




        
<div class="busuanzi-count">
  
  <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

  
    <span class="site-uv">
      <i class="fa fa-user"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
      
    </span>
  

  
    <span class="site-pv">
      <i class="fa fa-eye"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
      
    </span>
  
</div>








        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
          <span id="scrollpercent"><span>0</span>%</span>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>
<script src="https://cdn.jsdelivr.net/npm/jquery@2.1.3/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fastclick@1.0.6/lib/fastclick.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-lazyload@1.9.7/jquery.lazyload.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/velocity-animate@1.2.2/velocity.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/velocity-ui-pack@1.2.2/velocity.ui.min.js"></script>




  
  <script src="https://cdn.jsdelivr.net/npm/jquery-fancybox@2.0.0/source/js/jquery.fancybox.pack.js"></script>



  
  <script src="https://cdn.jsdelivr.net/npm/canvas-nest.js@1.0.0/canvas-nest.min.js"></script>












  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.3"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.3"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.3"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.3"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.3"></script>




  


  




	





  





  












  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('1');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  
  <script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js"></script>
  <script>AV.initialize("", "");</script>
  <script>
    function showTime(Counter) {
      var query = new AV.Query(Counter);
      var entries = [];
      var $visitors = $(".leancloud_visitors");

      $visitors.each(function () {
        entries.push( $(this).attr("id").trim() );
      });

      query.containedIn('url', entries);
      query.find()
        .done(function (results) {
          var COUNT_CONTAINER_REF = '.leancloud-visitors-count';

          if (results.length === 0) {
            $visitors.find(COUNT_CONTAINER_REF).text(0);
            return;
          }

          for (var i = 0; i < results.length; i++) {
            var item = results[i];
            var url = item.get('url');
            var time = item.get('time');
            var element = document.getElementById(url);

            $(element).find(COUNT_CONTAINER_REF).text(time);
          }
          for(var i = 0; i < entries.length; i++) {
            var url = entries[i];
            var element = document.getElementById(url);
            var countSpan = $(element).find(COUNT_CONTAINER_REF);
            if( countSpan.text() == '') {
              countSpan.text(0);
            }
          }
        })
        .fail(function (object, error) {
          console.log("Error: " + error.code + " " + error.message);
        });
    }

    function addCount(Counter) {
      var $visitors = $(".leancloud_visitors");
      var url = $visitors.attr('id').trim();
      var title = $visitors.attr('data-flag-title').trim();
      var query = new AV.Query(Counter);

      query.equalTo("url", url);
      query.find({
        success: function(results) {
          if (results.length > 0) {
            var counter = results[0];
            counter.fetchWhenSave(true);
            counter.increment("time");
            counter.save(null, {
              success: function(counter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(counter.get('time'));
              },
              error: function(counter, error) {
                console.log('Failed to save Visitor num, with error message: ' + error.message);
              }
            });
          } else {
            var newcounter = new Counter();
            /* Set ACL */
            var acl = new AV.ACL();
            acl.setPublicReadAccess(true);
            acl.setPublicWriteAccess(true);
            newcounter.setACL(acl);
            /* End Set ACL */
            newcounter.set("title", title);
            newcounter.set("url", url);
            newcounter.set("time", 1);
            newcounter.save(null, {
              success: function(newcounter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(newcounter.get('time'));
              },
              error: function(newcounter, error) {
                console.log('Failed to create');
              }
            });
          }
        },
        error: function(error) {
          console.log('Error:' + error.code + " " + error.message);
        }
      });
    }

    $(function() {
      var Counter = AV.Object.extend("Counter");
      if ($('.leancloud_visitors').length == 1) {
        addCount(Counter);
      } else if ($('.post-title-link').length > 1) {
        showTime(Counter);
      }
    });
  </script>



  

  

  
  
  
  <link rel="stylesheet" href="/lib/needsharebutton/needsharebutton.css">

  
  
  <script src="/lib/needsharebutton/needsharebutton.js"></script>

  <script>
    
      pbOptions = {};
      
          pbOptions.iconStyle = "box";
      
          pbOptions.boxForm = "horizontal";
      
          pbOptions.position = "bottomCenter";
      
          pbOptions.networks = "Weibo,Wechat,Douban,QQZone,Twitter,Facebook";
      
      new needShareButton('#needsharebutton-postbottom', pbOptions);
    
    
  </script>

  

  
  


  
  <script type="text/javascript" src="/js/src/js.cookie.js?v=5.1.3"></script>
  <script type="text/javascript" src="/js/src/scroll-cookie.js?v=5.1.3"></script>


  
  <script type="text/javascript" src="/js/src/exturl.js?v=5.1.3"></script>



  
  
<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>

<!-- 页面点击小红心 -->
<script type="text/javascript" src="/js/src/love.js"></script>


<script>
  console.log('%c本Blog仅用于个人学习',"color:orange; background:blue; font-size: 16pt");

  console.log('%c内容中有部分资源引用自互联网',"color:orange; background:blue; font-size: 16pt");

  console.log('%c如果不小心侵犯了您的权益，请联系  284141050@qq.com 处理相关信息',"color:orange; background:blue; font-size: 16pt");

</script>

</body>
</html>
